#ifndef __GPIO_H
#define __GPIO_H

//GPIO pin[0..7]
#define GPIO_Pin_0_7_Group      0
#define GPIO_Pin_0              (1<<0)
#define GPIO_Pin_1              (1<<1)
#define GPIO_Pin_2              (1<<2)
#define GPIO_Pin_3              (1<<3)
#define GPIO_Pin_4              (1<<4)
#define GPIO_Pin_5              (1<<5)
#define GPIO_Pin_6              (1<<6)
#define GPIO_Pin_7              (1<<7)	

//GPIO pin[8..15]
#define GPIO_Pin_8_15_Group     1
#define GPIO_Pin_8              (1<<0)
#define GPIO_Pin_9              (1<<1)
#define GPIO_Pin_10             (1<<2)
#define GPIO_Pin_11             (1<<3)
#define GPIO_Pin_12             (1<<4)
#define GPIO_Pin_13             (1<<5)
#define GPIO_Pin_14             (1<<6)
#define GPIO_Pin_15             (1<<7)

//GPIO pin[16..23]
#define GPIO_Pin_16_23_Group    2
#define GPIO_Pin_16             (1<<0)
#define GPIO_Pin_17             (1<<1)
#define GPIO_Pin_18             (1<<2)
#define GPIO_Pin_19             (1<<3)
#define GPIO_Pin_20             (1<<4)
#define GPIO_Pin_21             (1<<5)
#define GPIO_Pin_22             (1<<6)
#define GPIO_Pin_23             (1<<7)

//GPIO pin[24..31]
#define GPIO_Pin_24_31_Group    3
#define GPIO_Pin_24             (1<<0)
#define GPIO_Pin_25             (1<<1)
#define GPIO_Pin_26             (1<<2)
#define GPIO_Pin_27             (1<<3)
#define GPIO_Pin_28             (1<<4)
#define GPIO_Pin_29             (1<<5)
#define GPIO_Pin_30             (1<<6)
#define GPIO_Pin_31             (1<<7)

/**
    * @brief define input or output type
    */
typedef enum
{
    GPIO_Mode_IN        = 0x00,	/*!< Set gpio input*/
    GPIO_Mode_OUT       = 0x01	/*!< Set gpio output*/
}GPIO_Mode_TypeDef;

/**
    * @brief  define gpio pull up or pull down 
    */
typedef enum
{
    GPIO_PuPd_NOPULL = 0x00,	/*!< Set gpio hold*/
    GPIO_PuPd_UP     = 0x01,		/*!< Set gpio pull up*/
    GPIO_PuPd_DOWN   = 0x02	/*!< Set gpio pull down*/
}GPIOPuPd_TypeDef;

/**
  * @brief initialize gpio 
  * @param GPIO_Pin_Group : Total of four group, respectively are GPIO_Pin_0_7_Group,
  * 						GPIO_Pin_8_15_Group,GPIO_Pin_16_23_Group,GPIO_Pin_24_31_Group
  * @param GPIO_Pin : Each group contains seven pins : respectively are 
  *		GPIO_Pin_0 ~ GPIO_Pin_7,GPIO_Pin_8 ~ GPIO_Pin_15,GPIO_Pin_16 ~ GPIO_Pin_23,
  * @param GPIO_Mode : Init gpio output or input
  * @param GPIO_PuPd : Init gpio pull up or pull down or nopull
  * @return null
  */
void GPIO_Init(u8_t GPIO_Pin_Group, u8_t GPIO_Pin, GPIO_Mode_TypeDef GPIO_Mode, GPIOPuPd_TypeDef GPIO_PuPd);

/**
  * @brief Sets the output state of a set of GPIO. Only the GPIO is valid for the output state
  * @param GPIO_Pin_Group : contains four group 
  * @paran GPIO_Val : A byte corresponds to a group of gpio ,1 is high,0 is low
  * @return null
  */
void GPIO_Write(u8_t GPIO_Pin_Group, u8_t GPIO_Val);

/**
  * @brief Set an GPIO output level
  * @param GPIO_Pin_Group : The group that gpio is in
  * @param GPIO_Pin : gpio pin number
  * @return null
  */
void GPIO_WriteBit(u8_t GPIO_Pin_Group, u8_t GPIO_Pin, BitAction GPIO_BitVal);

/**
  * @brief Setting a gpio high level
  * @param GPIO_Pin_Group : The group that gpio is in
  * @param GPIO_Pin : gpio pin number
  * @return null
  */
void GPIO_SetHighBits(u8_t GPIO_Pin_Group, u8_t GPIO_Pin);

/**
  * @brief Setting a gpio low level
  * @param GPIO_Pin_Group : The group that gpio is in
  * @param GPIO_Pin : gpio pin number
  * @return null
  */
void GPIO_SetlowBits(u8_t GPIO_Pin_Group, u8_t GPIO_Pin);

/**
  * @brief Set an GPIO output level to reverse the output value of the Pin specified in a set of GPIO.
  * @param GPIO_Pin_Group : A group of gpio that will be flipped
  * @param GPIO_Pin : Reverse Mask, IO inversion corresponding to "1" in 8bit, IO inversion 
  *  				     corresponding to "0" does not reverse
  * @return null
  */
void GPIO_ToggleBits(u8_t GPIO_Pin_Group, u8_t GPIO_Pin);

/**
  * @brief Read a group of values that enter GPIO.
  * @param GPIO_Pin_Group : A group of input gpio to read
  * @return a byte of data representing the input state of a group of gpio
  */
u8_t GPIO_ReadInputData(u8_t GPIO_Pin_Group);


/**
  * @brief Read a group of values of the output GPIO.
  * @param GPIO_Pin_Group : A group of output gpio to read
  * @return a byte of data representing the output state of a group of gpio
  */
u8_t GPIO_ReadOutputData(u8_t GPIO_Pin_Group);

/**
  * @brief Read the status of the input GPIO bit by bit
  * @param GPIO_Pin_Group : The group that gpio is in
  * @param GPIO_Pin : gpio pin number
  *  return The input GPIO level of the read,HIGH 0r LOW
  */
BitStatus GPIO_ReadInputDataBit(u8_t GPIO_Pin_Group, u8_t GPIO_Pin);

/**
  * @brief Read the status of the output GPIO bit by bit
  * @param GPIO_Pin_Group : The group that gpio is in
  * @param GPIO_Pin : gpio pin number
  *  return The output GPIO level of the read,HIGH or LOW
  */
BitStatus GPIO_ReadOutputDataBit(u8_t GPIO_Pin_Group, u8_t GPIO_Pin);

/**
  * @brief Set GPIO to high or low wake up
  * @param GPIO_Pin_Group : The group that gpio is in
  * @param GPIO_Pin : gpio pin number
  * @param NewState : Turn on 0r off the wake up function flag,DISABLE means 
  *   					turning off,ENABLE means turning on
  * @param GPIO_BitVal : Setting the wake level,HIGH represents that the input high level can be awakened
  *  					LOW represents that the input low level can be awakened
  * @return null
  */	
void GPIO_SetWakeup(u8_t GPIO_Pin_Group, u8_t GPIO_Pin, FunctionalState NewState, BitAction GPIO_BitVal);

/**
  * @brief Gets which GPIO in a group of GPIO are high and which are low.
  * @param GPIO_Pin_Group : The group that gpio is in
  * @param GPIO_BitVal : When is HIGH, represents the HIGH level awakening of the group of gpio
  *					When is LOW, represents the LOW level awakening of the group of gpio
  * return an 8-bit unsigned number.A bit of 1 indicates that the corresponding GPIO is effectively HIGH 
  *			or LOW, depending on whether it is passed in HIGH or LOW.
  */
u8_t GPIO_GetWakeup(u8_t GPIO_Pin_Group, BitAction GPIO_BitVal);

BitStatus KeyStateRead(u8_t GPIO_Pin_Group, u8_t GPIO_Pin);

bool Check_WakeUp(u8_t GPIO_Pin_Group, u8_t GPIO_Pin,GPIO_Mode_TypeDef 
						GPIO_Mode,BitStatus GPIO_BitVal);
#endif

